package pCloud.stream;

import java.util.Vector;
	
/*
 * Aurora Query Graph class
 */

public class QueryGraph {
	
	public Stream InputStream;
	public Vector<FilterBox> FB;
	public Vector<MapBox> MB;
	public Vector<AggregateBox> AB;
	
	public String OutputStreamName;
	
	
	public QueryGraph(){
		
		this.InputStream= new Stream();
		this.FB = new Vector<FilterBox>();
		this.MB = new Vector<MapBox>();
		this.AB = new Vector<AggregateBox>();
	}
			
	public void print(){
		
		this.InputStream.print();
		System.out.println("Map Boxes : ");
		for (int i=0; i<this.MB.size();i++){
			this.MB.elementAt(i).print();			
		}
		System.out.println("Filter Boxes : ");
		for (int i=0; i<this.FB.size();i++){
			this.FB.elementAt(i).print();			
		}
		
		System.out.println("Aggregate Boxes : ");
		for (int i=0; i<this.AB.size();i++){
			this.AB.elementAt(i).print();			
		}
	}
	

	public String createSSQL() {
		
		/*
		 * Generate a SSQL script for the Query Graph object
		 * General order: Filter Box -> Map Box ->  AggregateBox
		 * Assumption: Multiple or Single FB, Single MB, Single AB
		 * case 1 : Single FB
		 * case 2 : Single FB -> Single MB
		 * case 3 : Single FB -> Single AB
		 * case 4 : Single FB -> Single MB -> Single AB
		 * case 5 : Multiple FB
		 * case 6 : Multiple FB -> Single MB
		 * case 7 : Multiple FB -> Single AB
		 * case 8 : Multiple FB -> Single MB -> Single AB
		 * case 9 : Single MB
		 * case 10: Single MB -> Single AB
		 * case 11: Single AB
		 * 
		 */
		
		String ssql = "";
		
		ssql += this.InputStream.createSSQL();
		
		int internalstreamindex = 0;
			
				
		//case 1 : Single FB
		
		if(this.FB.size()==1 && this.MB.size()==0 && this.AB.size() ==0 ){
			System.out.println("Case 1...");
			this.OutputStreamName = "out_" + internalstreamindex;
			System.out.println("output stream name : " + this.OutputStreamName);
			ssql += "CREATE OUTPUT STREAM " + this.OutputStreamName + ";" + Global.eol;
			ssql += this.FB.elementAt(0).createSSQL(this.InputStream.name, this.OutputStreamName) + Global.eol;
		}
		
		//case 2 : Single FB -> Single MB
		
		if(this.FB.size()==1 && this.MB.size()==1 && this.AB.size() ==0 ){
			System.out.println("Case 2...");
			String internalstream = "internal_" + internalstreamindex;
			internalstreamindex ++;
			ssql += "CREATE STREAM " + internalstream + ";" + Global.eol;
			ssql += this.FB.elementAt(0).createSSQL(this.InputStream.name, internalstream);
			
			this.OutputStreamName = "out_" + internalstreamindex;
			ssql += "CREATE OUTPUT STREAM " + this.OutputStreamName + ";" + Global.eol;
			ssql += this.MB.elementAt(0).createSSQL(internalstream, this.OutputStreamName) + Global.eol;
			
		}
		
		//case 3 : Single FB -> Single AB
		
		if(this.FB.size()==1 && this.MB.size()==0 && this.AB.size() ==1 ){
			
			System.out.println("Case 3...");
			
			String internalstream = "internal_" + internalstreamindex;
			internalstreamindex ++;
			ssql += "CREATE STREAM " + internalstream + ";" + Global.eol;
			ssql += this.FB.elementAt(0).createSSQL(this.InputStream.name, internalstream) + Global.eol;
			
			this.OutputStreamName = "out_" + internalstreamindex;
			ssql += "CREATE OUTPUT STREAM " + this.OutputStreamName + ";" + Global.eol;
			ssql += this.AB.elementAt(0).createSSQL(internalstream, this.OutputStreamName) + Global.eol;
		}
		
		//case 4 : Single FB -> Single MB -> Single AB
		
		if(this.FB.size()==1 && this.MB.size()==1 && this.AB.size() ==1 ){
			
			System.out.println("Case 4...");
			
			String internalstream = "internal_" + internalstreamindex;
			internalstreamindex ++;
			ssql += "CREATE STREAM " + internalstream + ";" + Global.eol;
			ssql += this.FB.elementAt(0).createSSQL(this.InputStream.name, internalstream);
			
			String internalstream_2 = internalstream;
			internalstream = "internal_" + internalstreamindex;
			internalstreamindex ++;
			
			ssql += "CREATE STREAM " + internalstream + ";" + Global.eol;
			ssql += this.MB.elementAt(0).createSSQL(internalstream_2, internalstream) + Global.eol;
			
			this.OutputStreamName = "out_" + internalstreamindex;
			ssql += "CREATE OUTPUT STREAM " + this.OutputStreamName + ";" + Global.eol;
			ssql += this.AB.elementAt(0).createSSQL(internalstream, this.OutputStreamName) + Global.eol;
			
		}
		
		
		//case 5 : Multiple FB
		
		if(this.FB.size()> 1 && this.MB.size()==0 && this.AB.size() ==0 ){
			System.out.println("Case 5...");
			String internalstream = this.InputStream.name;
			String internalstream_2 = "internal_" + internalstreamindex;
			
			
			for(int i=0; i<this.FB.size()-1; i++ ){
				
				ssql += "CREATE STREAM " + internalstream_2 + ";" + Global.eol; 
				ssql += this.FB.elementAt(i).createSSQL(internalstream, internalstream_2) + Global.eol;
				internalstream = internalstream_2;
				internalstreamindex ++;
				internalstream_2="internal_" + internalstreamindex;
			}
			
			this.OutputStreamName = "out_" + internalstreamindex;
			ssql += "CREATE OUTPUT STREAM " + this.OutputStreamName + ";" + Global.eol;
			ssql += this.FB.elementAt(this.FB.size()-1).createSSQL(internalstream, this.OutputStreamName) + Global.eol;
		}
		
		//case 6 : Multiple FB -> Single MB
		
		if(this.FB.size()> 1 && this.MB.size()==1 && this.AB.size() ==0 ){
			System.out.println("Case 6...");
			String internalstream = this.InputStream.name;
			String internalstream_2 = "internal_" + internalstreamindex;
			
			for(int i=0; i<this.FB.size(); i++ ){
				
				ssql += "CREATE STREAM " + internalstream_2 + ";" + Global.eol; 
				ssql += this.FB.elementAt(i).createSSQL(internalstream, internalstream_2) + Global.eol;
				internalstream = internalstream_2;
				internalstreamindex ++;
				internalstream_2="internal_" + internalstreamindex;
			}
			
			this.OutputStreamName = "out_" + internalstreamindex;
			ssql += "CREATE OUTPUT STREAM " + this.OutputStreamName + ";" + Global.eol;
			ssql += this.MB.elementAt(0).createSSQL(internalstream, this.OutputStreamName) + Global.eol;
			
		}
		//case 7 : Multiple FB -> Single AB
		
		if(this.FB.size()> 1 && this.MB.size()==0 && this.AB.size() ==1 ){
			System.out.println("Case 7...");
			String internalstream = this.InputStream.name;
			String internalstream_2 = "internal_" + internalstreamindex;
			
			for(int i=0; i<this.FB.size(); i++ ){
				
				ssql += "CREATE STREAM " + internalstream_2 + ";" + Global.eol; 
				ssql += this.FB.elementAt(i).createSSQL(internalstream, internalstream_2) + Global.eol;
				internalstream = internalstream_2;
				internalstreamindex ++;
				internalstream_2="internal_" + internalstreamindex;
			}
			
			this.OutputStreamName = "out_" + internalstreamindex;
			ssql += "CREATE OUTPUT STREAM " + this.OutputStreamName + ";" + Global.eol;
			ssql += this.AB.elementAt(0).createSSQL(internalstream, this.OutputStreamName) + Global.eol;			
		}
		
		//case 8 : Multiple FB -> Single MB -> Single AB
		
		if(this.FB.size()> 1 && this.MB.size()==1 && this.AB.size() ==1 ){
			System.out.println("Case 8...");
			String internalstream = this.InputStream.name;
			String internalstream_2 = "internal_" + internalstreamindex;
			
			for(int i=0; i<this.FB.size(); i++ ){
				
				ssql += "CREATE STREAM " + internalstream_2 + ";" + Global.eol; 
				ssql += this.FB.elementAt(i).createSSQL(internalstream, internalstream_2) + Global.eol;
				internalstream = internalstream_2;
				internalstreamindex ++;
				internalstream_2="internal_" + internalstreamindex;
			}
			
			ssql += "CREATE OUTPUT STREAM " + internalstream_2 + ";" + Global.eol;
			ssql += this.MB.elementAt(0).createSSQL(internalstream, internalstream_2) + Global.eol;
			
			internalstreamindex ++;
			this.OutputStreamName = "out_" + internalstreamindex;
			ssql += "CREATE OUTPUT STREAM " + this.OutputStreamName + ";" + Global.eol;
			ssql += this.AB.elementAt(0).createSSQL(internalstream_2, this.OutputStreamName) + Global.eol;
			
			
		}
		
		//case 9 : Single MB
		if(this.FB.size()== 0 && this.MB.size()==1 && this.AB.size() ==0 ){
			System.out.println("Case 9...");
			this.OutputStreamName = "out_" + internalstreamindex;
			System.out.println("output stream name : " + this.OutputStreamName);
			ssql += "CREATE OUTPUT STREAM " + this.OutputStreamName + ";" + Global.eol;
			ssql += this.MB.elementAt(0).createSSQL(this.InputStream.name, this.OutputStreamName) + Global.eol;
		}
		
		//case 10: Single MB -> Single AB
		
		if(this.FB.size()== 0 && this.MB.size()==1 && this.AB.size() ==1 ){
			System.out.println("Case 10...");
			String internalstream = "internal_" + internalstreamindex;
			internalstreamindex ++;
			ssql += "CREATE STREAM " + internalstream + ";" + Global.eol;
			ssql += this.MB.elementAt(0).createSSQL(this.InputStream.name, internalstream);
			
			this.OutputStreamName = "out_" + internalstreamindex;
			ssql += "CREATE OUTPUT STREAM " + this.OutputStreamName + ";" + Global.eol;
			ssql += this.AB.elementAt(0).createSSQL(internalstream, this.OutputStreamName) + Global.eol;
			
			
		}
		
		//case 11: Single AB
		
		if(this.FB.size()== 0 && this.MB.size()==0 && this.AB.size() ==1 ){
			System.out.println("Case 11...");
			this.OutputStreamName = "out_" + internalstreamindex;
			System.out.println("output stream name : " + this.OutputStreamName);
			ssql += "CREATE OUTPUT STREAM " + this.OutputStreamName + ";" + Global.eol;
			ssql += this.AB.elementAt(0).createSSQL(this.InputStream.name, this.OutputStreamName) + Global.eol;
		}
				
		return ssql;
				
	}
}
